﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace NetWork.Enthernet
{
    /// <summary>
    /// 发布订阅类的客户端，使用指定的关键订阅相关的数据推送信息
    /// </summary>
    public class NetPushClient : NetworkXBase
    {
        #region Constructor
        /// <summary>
        /// 实例化一个发布订阅类的客户端，需要指定ip地址，端口，及订阅关键字
        /// </summary>
        /// <param name="ipAddress">服务器的IP地址</param>
        /// <param name="port">服务器的端口号</param>
        /// <param name="key">订阅关键字</param>
        public NetPushClient(string ipAddress, int port, string key)
        {
            endPoint = new IPEndPoint(IPAddress.Parse(ipAddress), port);
            keyWord = key;
            if (string.IsNullOrEmpty(key))
            {
                throw new Exception("关键字不允许为空");
            }
        }
        #endregion
        #region NetworkXBase Override
        internal override void DataProcessingCenter(AppSession session, int protocol, int customer, byte[] content)
        {
            if (protocol == HslProtocol.ProtocolUserString)
            {
                if (action != null) action.Invoke(this, Encoding.Unicode.GetString(content));
                if (OnReceived != null) OnReceived.Invoke(this, Encoding.Unicode.GetString(content));
            }
        }
        internal override void SocketReceiveException(AppSession session, Exception ex)
        {
            // 发生异常的时候需要进行重新连接
            while (true)
            {
                Console.WriteLine(ex);
                Console.WriteLine("在10秒后重新连接服务器");
                System.Threading.Thread.Sleep(this.reconnectTime);
                if (CreatePush().Success)
                {
                    Console.WriteLine("重连服务器成功");
                    break;
                }
            }
        }
        #endregion
        #region Public Method
        /// <summary>
        /// 创建数据推送服务
        /// </summary>
        /// <param name="pushCallBack">触发数据推送的委托</param>
        /// <returns>是否创建成功</returns>
        public Result CreatePush(Action<NetPushClient, string> pushCallBack)
        {
            action = pushCallBack;
            return CreatePush();
        }
        /// <summary>
        /// 创建数据推送服务，使用事件绑定的机制实现
        /// </summary>
        /// <returns>是否创建成功</returns>
        public Result CreatePush()
        {
            if (CoreSocket != null) CoreSocket.Close();
            // 连接服务器
            Result<Socket> connect = CreateSocketAndConnect(endPoint, 5000);
            if (!connect.Success) return connect;
            // 发送订阅的关键字
            Result send = SendStringAndCheckReceive(connect.Data, 0, keyWord);
            if (!send.Success) return send;
            // 确认服务器的反馈
            Result<int, string> receive = ReceiveStringContentFromSocket(connect.Data);
            if (!receive.Success) return receive;
            // 订阅不存在
            if (receive.Data1 != 0)
            {
                connect.Data.Close();
                return new Result(receive.Data2);
            }
            // 异步接收
            AppSession appSession = new AppSession();
            CoreSocket = connect.Data;
            appSession.WorkSocket = connect.Data;
            ReBeginReceiveHead(appSession, false);
            return Result.CreateSuccessResult();
        }
        /// <summary>
        /// 关闭消息推送的界面
        /// </summary>
        public void ClosePush()
        {
            action = null;
            if (CoreSocket != null && CoreSocket.Connected)
            {
                CoreSocket.Send(BitConverter.GetBytes(100));
                CoreSocket.Close();
            }
        }
        #endregion
        #region Public Properties
        /// <summary>
        /// 本客户端的关键字
        /// </summary>
        public string KeyWord { get { return keyWord; } }
        /// <summary>
        /// 获取或设置重连服务器的间隔时间
        /// </summary>
        public int ReConnectTime { set { reconnectTime = value; } get { return reconnectTime; } }
        #endregion
        #region Public Event
        /// <summary>
        /// 当接收到数据的事件信息，接收到数据的时候触发。
        /// </summary>
        public event Action<NetPushClient, string> OnReceived;
        #endregion
        #region Private Member
        private IPEndPoint endPoint;                           // 服务器的地址及端口信息
        private string keyWord = string.Empty;                 // 缓存的订阅关键字
        private Action<NetPushClient, string> action;          // 服务器推送后的回调方法
        private int reconnectTime = 10000;                     // 重连服务器的时间
        #endregion
        #region Object Override
        /// <summary>
        /// 返回表示当前对象的字符串
        /// </summary>
        /// <returns>字符串</returns>
        public override string ToString()
        {
            return "NetPushClient[" + endPoint.ToString() + "]";
        }
        #endregion
    }
}
